{
 "cells": [
  {
   "cell_type": "markdown",
   "id": "38fc78b4-0209-4d22-bffb-011899251dca",
   "metadata": {},
   "source": [
    "## 面向对象实现方法\n",
    "类的定义公式"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "20e370b5-4113-481b-a67b-9e613340014a",
   "metadata": {},
   "outputs": [],
   "source": [
    "class 类名(父类):\n",
    "    属性名 = 属性值"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "e19182d3-71e1-4817-9852-577f4bb0f875",
   "metadata": {},
   "source": [
    "以上公式中类名称后面的括号，可写可不写，当写上的时候，一般里面都要写上父类。如果不写，则默认继承object类，它是所有类的祖先。"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "f6a8a811-cfbd-4b5e-8bb9-ab84e8eb0102",
   "metadata": {},
   "source": [
    "## self\n",
    "self是指调用该函数的对象，也可以指代类的对象"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "fc9e08f4-0e95-4eae-b69f-1ddb4c55465b",
   "metadata": {},
   "source": [
    "## 添加和获取对象属性\n",
    "- 属性即使特征。\n",
    "- 对象的权力是非常大的，可以调用本类中的所有属性和方法。\n",
    "- 对象既可以在类的外面添加和获取，还可以在类内部添加和获取"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "ed24776d-313f-49f4-b0b5-436a80be8736",
   "metadata": {},
   "source": [
    "## 对象内存分析\n",
    "- 在Python中，每一个对象都会依据其所对应的类型进行创建，同时在不同对象中，也会保存有各自的属性内容\n",
    "- 所以以上的程序可以得出结论，class类也属于引用数据类型，所以类产生的对象也可以进行引用类型传递，【引用传递时对象所传递的是其所对应的内存地址】\n",
    "- 将一个类的对象，作为参数传递到任意一个外部函数的参数中，这样这个函数就会跟这个类产生关系"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "f5d9b8a6-e07e-450c-abc3-5b7d43cfc7c7",
   "metadata": {},
   "outputs": [],
   "source": [
    "#coding:UTF-8\n",
    "class Member:    #自定义Member类\n",
    "    pass    #不定义内容\n",
    "\n",
    "def main():    #主函数\n",
    "    mem = Member()    #实例化对象\n",
    "    mem.name = \"张三\"\n",
    "    mem.age = 18\n",
    "    print(\"姓名：%s, 年龄：%d\")"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "a296ef71-20ed-444d-b255-8957b15cd872",
   "metadata": {},
   "source": [
    "对象引用传递"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "18b742f9-4111-4964-ac2d-288e5d65d61e",
   "metadata": {},
   "outputs": [],
   "source": [
    "#coding:UTF-8\n",
    "class Member:    #自定义Member类\n",
    "    def get_info(self):    #定义方法\n",
    "        return \"姓名：%s，年龄：%d\" % (self.name, self.age)    #返回对象信息\n",
    "        \n",
    "def change_member(temp):    #定义函数在类的外部定义\n",
    "    \"\"\"\n",
    "    定义一个修改函数，该函数的主要功能\n",
    "    \"\"\"\n",
    "    \n"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "258272af-4951-4228-8357-1c9bcd4d9776",
   "metadata": {},
   "source": [
    "## 引用与垃圾\n",
    "在Python中每一块内存都可以被不同的对象同时指向，这些对象可以同时对内存中的数据进行操作，但是每一个对象只允许保存一个引用地址，如果现在引用地址发生了改变，则就会断开已经引用的内存空间指向新的内存空间"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "e1b0615a-4526-4fcf-aac5-dee561ec713c",
   "metadata": {},
   "source": [
    "修改对象引用"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 1,
   "id": "4cf1a4d7-9ae2-401a-945b-ef0444e5b478",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "【引用传递】mem_a对象地址：2004921105104、mem_b对象地址：2004921101888\n",
      "姓名：河南师范大学，年龄：5\n",
      "【引用传递】mem_a对象地址：2004921101888、mem_b对象地址：2004921101888\n"
     ]
    }
   ],
   "source": [
    "#coding:UTF-8\n",
    "class Member:\n",
    "    def set_info(self, name, age):\n",
    "        self.name = name    #设置name属性内容\n",
    "        self.age = age\n",
    "    def get_info(self):\n",
    "        return \"姓名：%s，年龄：%d\" % (self.name, self.age)    #以字符串的形式返回内容\n",
    "\n",
    "def main():\n",
    "    mem_a = Member()    #实例化Member对象，其中mem_a开辟一块内存空间\n",
    "    mem_b = Member()    #实例化Member对象，其中mem_b开辟一块内存空间 \n",
    "    mem_a.set_info(\"张三\", 18)          #设置实例属性内容\n",
    "    mem_b.set_info(\"河南师范大学\", 5)    #设置实例属性内容\n",
    "    print(\"【引用传递】mem_a对象地址：%d、mem_b对象地址：%d\" % (id(mem_a), id(mem_b)))\n",
    "    mem_a = mem_b                       #【引用传递】 将mem_b的内存地址指向mem_a的内存地址\n",
    "    print(mem_a.get_info())             #输出 对象.方法()\n",
    "    print(\"【引用传递】mem_a对象地址：%d、mem_b对象地址：%d\" % (id(mem_a), id(mem_b)))\n",
    "\n",
    "if __name__ == \"__main__\":    #判断函数的执行名称，可写可不写\n",
    "    main()                    #调用主函数"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "3b61ee3f-5967-4f64-bdc5-b2683b2d3edd",
   "metadata": {},
   "source": [
    "## 面向对象 --继承\n",
    "- 在Python中，所有类默认继承object类，object类是顶级类的集成，其它类叫做派生类"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "4c028b62-2079-484c-b2b6-a94d5edac378",
   "metadata": {},
   "source": [
    "### 单继承"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 3,
   "id": "7c9f5635-3244-4b36-80b6-b67a49250e41",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "1\n"
     ]
    }
   ],
   "source": [
    "#coding:UTF-8\n",
    "#父类\n",
    "class  Father(object):\n",
    "    def __init__(self):\n",
    "        self.num = 1\n",
    "\n",
    "    def info_print(self):\n",
    "        print(self.num)\n",
    "\n",
    "#子类\n",
    "class Son(Father):\n",
    "    pass\n",
    "\n",
    "if __name__ == '__main__':\n",
    "    #创建对象\n",
    "    result_son = Son()    #子类实例化对象\n",
    "    result_son.info_print()    #子类既然继承了父类，那么就默认继承了父类中的所有属性和方法"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 4,
   "id": "118af401-dcb7-4497-b562-5ce1943ed126",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "[七十二变绝学]\n",
      "运用[七十二变绝学]习得这项技能\n"
     ]
    }
   ],
   "source": [
    "#单继承\n",
    "#coding:UTF-8\n",
    "\n",
    "#定义师傅类\n",
    "class Master(object):\n",
    "    def __init__(self):    #定义初始化函数，也叫构造函数\n",
    "        self.transformer = '[七十二变绝学]'\n",
    "\n",
    "    def make_kongfu(self):\n",
    "        print(f\"运用{self.transformer}习得这项技能\")\n",
    "\n",
    "#定义徒弟类\n",
    "class Prentice(Master):\n",
    "    pass\n",
    "\n",
    "if __name__ == '__main__':\n",
    "    #创建对象\n",
    "    learn = Prentice()    #实例化子类对象\n",
    "    #对象访问实例属性\n",
    "    print(learn.transformer)\n",
    "    #对象调用实例方法\n",
    "    learn.make_kongfu()"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "225fc0f3-23a5-4898-a34e-68300440c51d",
   "metadata": {},
   "source": [
    "### 多继承\n",
    "一个徒弟继承多个师傅，当多个属性一致，以第一个师傅为准"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 6,
   "id": "298a87db-d962-404c-a564-96adffa542d9",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "[七十二变绝学]\n",
      "运用[七十二变绝学]习得这项技能\n"
     ]
    }
   ],
   "source": [
    "#coding:UTF-8\n",
    "# 定义师傅类\n",
    "class Master(object):\n",
    "    def __init__(self):    #定义初始化函数，也叫构造函数\n",
    "        self.transformer = '[七十二变绝学]'\n",
    "\n",
    "    def make_kongfu(self):\n",
    "        print(f\"运用{self.transformer}习得这项技能\")\n",
    "\n",
    "#找到另一个师傅，习得长生不老之术\n",
    "class AnMaster(object):\n",
    "    def __init__(self):    \n",
    "        self.transformer = '[长生不老，秘密存在于基因当中，与自由基有关]'\n",
    "\n",
    "class Prentice(Master, AnMaster):\n",
    "    pass\n",
    "\n",
    "if __name__ == '__main__':\n",
    "    #创建对象\n",
    "    learn = Prentice()    #实例化子类对象\n",
    "    #对象访问实例属性\n",
    "    print(learn.transformer)\n",
    "    #对象调用实例方法\n",
    "    learn.make_kongfu()"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "305ff04e-413d-4582-8bbb-f4efa2e17d6f",
   "metadata": {},
   "source": [
    "### 子类重写父类同名方法和属性"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 20,
   "id": "8e18eb75-8450-4788-a271-0245b5e549d6",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "[长生不老，秘密存在于基因当中，与自由基有关]\n",
      "[习得了七十二变绝学： 这是跟第一个师傅学的]\n",
      "习得这项技能\n"
     ]
    }
   ],
   "source": [
    "#子类重写父类同名方法和属性\n",
    "#coding:UTF-8\n",
    "# 定义师傅类\n",
    "class Master(object):\n",
    "    def send(self, msg):\n",
    "        print('[习得了七十二变绝学： %s]' % (msg))\n",
    "        \n",
    "    \n",
    "#找到另一个师傅，习得长生不老之术\n",
    "class AnMaster(object):\n",
    "    def build(self):\n",
    "        print('[长生不老，秘密存在于基因当中，与自由基有关]')\n",
    "        return True\n",
    "    def make_kongfu(self):\n",
    "        print(\"习得这项技能\")\n",
    "\n",
    "#定义徒弟类\n",
    "class Prentice(Master, AnMaster):\n",
    "    def kongfu_message(self, msg):   #通道测试\n",
    "        if  self.build():   #调用父类方法\n",
    "            self.send(msg)    #调用父类方法\n",
    "            self.make_kongfu()    #调用父类方法\n",
    "\n",
    "def main():\n",
    "    kf = Prentice()    #实例化对象\n",
    "    kf.kongfu_message('这是跟第一个师傅学的')\n",
    "\n",
    "if __name__ == '__main__':\n",
    "    main()"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "3267fc2e-4a9f-4359-8955-7c04e7c13363",
   "metadata": {},
   "source": [
    "### 子类调用父类的同名方法和属性"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 5,
   "id": "177a4b36-07f5-4402-9584-10735d0e14d5",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "运用[独创本领--变大变小]习得这项技能\n",
      "运用[长生不老，秘密存在于基因当中，与自由基有关]习得这项技能\n",
      "运用[独创本领--变大变小]习得这项技能\n"
     ]
    }
   ],
   "source": [
    "#coding:UTF-8\n",
    "\n",
    "#定义师傅类\n",
    "class Master(object):\n",
    "    def __init__(self):\n",
    "        self.transformer = '[七十二变绝学]'\n",
    "\n",
    "    def make_kongfu(self):\n",
    "        print(f'运用{self.transformer}习得这项技能')\n",
    "\n",
    "#创建另一个师傅类\n",
    "class AnMaster(object):\n",
    "    def __init__(self):\n",
    "        self.transformer = '[长生不老，秘密存在于基因当中，与自由基有关]'\n",
    "\n",
    "    def make_kongfu(self):\n",
    "        print(f'运用{self.transformer}习得这项技能')\n",
    "\n",
    "#定义徒弟类\n",
    "class Prentice(AnMaster, Master):\n",
    "    def __init__(self):\n",
    "        self.transformer = '[独创本领--变大变小]'\n",
    "        \n",
    "    def make_kongfu(self):\n",
    "        self.__init__()\n",
    "        print(f'运用{self.transformer}习得这项技能')\n",
    "\n",
    "    def make_master_kongfu(self):\n",
    "        Master.__init__(self)\n",
    "        Master.make_kongfu(self)\n",
    "\n",
    "    def make_anmaster_kongfu(self):\n",
    "        AnMaster.__init__(self)\n",
    "        AnMaster.make_kongfu(self) \n",
    "\n",
    "\n",
    "if __name__ == \"__main__\":\n",
    "    #创建对象\n",
    "    learn = Prentice()\n",
    "\n",
    "    learn.make_kongfu()\n",
    "\n",
    "    # learn.make_master_kongfu()\n",
    "    learn.make_anmaster_kongfu()\n",
    "\n",
    "    learn.make_kongfu()  "
   ]
  },
  {
   "cell_type": "markdown",
   "id": "f8d1fb0f-94aa-4b3e-b5a5-42a519fc434a",
   "metadata": {},
   "source": [
    "## 多层继承"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 8,
   "id": "08fe4557-a4d2-40e9-9efb-228c31a83f65",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "运用[独创能力-变大变小]习得这项技能\n",
      "运用[七十二变绝学]习得这项技能\n",
      "运用[长生不老，秘密存在于基因当中，与自由基有关]习得这项技能\n"
     ]
    }
   ],
   "source": [
    "#coding:UTF-8\n",
    "\n",
    "#定义师傅类\n",
    "class Master(object):\n",
    "    def __init__(self):\n",
    "        self.transformer = '[七十二变绝学]'\n",
    "\n",
    "    def make_kongfu(self):\n",
    "        print(f'运用{self.transformer}习得这项技能')\n",
    "\n",
    "#定义另一个师傅类\n",
    "class AnMaster(object):\n",
    "    def __init__(self):\n",
    "        self.transformer = '[长生不老，秘密存在于基因当中，与自由基有关]'\n",
    "\n",
    "    def make_kongfu(self):\n",
    "        print(f'运用{self.transformer}习得这项技能')\n",
    "\n",
    "#定义徒弟类\n",
    "class Prentice(AnMaster, Master):\n",
    "    def __init__(self):\n",
    "        self.transformer = '[独创能力-变大变小]'\n",
    "\n",
    "    def make_kongfu(self):\n",
    "        #【如果先调用了父类的属性和方法，父类属性会覆盖子类属性】 故在调用属性前，先调用自己子类的初始化\n",
    "        self.__init__()\n",
    "        print(f'运用{self.transformer}习得这项技能')\n",
    "\n",
    "    # 调用父类方法，但是为了保证调用到的是父类的属性，必须在调用方法之前调用父类的初始化\n",
    "    def make_master_kongfu(self):\n",
    "        Master.__init__(self)\n",
    "        Master.make_kongfu(self)\n",
    "\n",
    "    def make_anmaster_kongfu(self):\n",
    "        AnMaster.__init__(self)\n",
    "        AnMaster.make_kongfu(self)\n",
    "\n",
    "#徒孙类\n",
    "class Tusun(Prentice):\n",
    "    pass\n",
    "\n",
    "if __name__ == \"__main__\":\n",
    "    #创建对象\n",
    "    xiaoan = Tusun()\n",
    "    xiaoan.make_kongfu()\n",
    "    xiaoan.make_master_kongfu()\n",
    "    xiaoan.make_anmaster_kongfu()"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "80c239c0-065a-419b-a845-c4f07ff1d29d",
   "metadata": {},
   "source": [
    "## super()函数"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 14,
   "id": "8ec6d605-6764-482f-b387-d2aa3afb802c",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "运用[七十二变绝学]习得这项技能\n",
      "运用[独创能力-变大变小]习得这项技能\n",
      "运用[七十二变绝学]习得这项技能\n"
     ]
    }
   ],
   "source": [
    "#coding:UTF-8\n",
    "\n",
    "#定义师傅类\n",
    "class Master(object):\n",
    "    def __init__(self):\n",
    "        self.transformer = '[七十二变绝学]'\n",
    "\n",
    "    def make_kongfu(self):\n",
    "        print(f'运用{self.transformer}习得这项技能')\n",
    "\n",
    "#创建另一个类\n",
    "class AnMaster(Master):\n",
    "    def __init__(self):\n",
    "        super().__init__()    #使用super()调用父类的初始化方法\n",
    "\n",
    "    def make_kongfu(self):\n",
    "        print(f\"运用{self.transformer}习得这项技能\")\n",
    "\n",
    "    def make_master_kongfu(self):\n",
    "        super().__init__()\n",
    "        #不需要再次初始化\n",
    "        super().make_kongfu()    #使用super()调用父类的方法\n",
    "\n",
    "    def make_old_kongfu(self):\n",
    "        super().__init__()    #同上\n",
    "        super().make_kongfu()    #同上\n",
    "\n",
    "#定义徒弟类，继承自AnMaster\n",
    "class Prentice(AnMaster):\n",
    "    def __init__(self):    #在使用super()之前，\n",
    "        super().__init__()    #使用super()调用父类的初始化方法\n",
    "        #self.transformer = '[独创能力-变大变小]'\n",
    "\n",
    "    def make_kongfu(self):\n",
    "        self.transformer = '[独创能力-变大变小]'\n",
    "        print(f'运用{self.transformer}习得这项技能')\n",
    "\n",
    "    def make_master_kongfu(self):\n",
    "        super().__init__()    #不需要再次初始化，但这里是为了获取父类的属性\n",
    "        super().make_kongfu()    #使用super调用父类的方法\n",
    "\n",
    "    def make_old_kongfu(self):\n",
    "        super().__init__()    #同上\n",
    "        super().make_kongfu()    #同上\n",
    "    \n",
    "\n",
    "#徒孙类，继承自Prentice\n",
    "class Tusun(Prentice):\n",
    "    pass\n",
    "\n",
    "if __name__ == '__main__':\n",
    "    #创建对象\n",
    "    learn = Prentice()\n",
    "    learn.make_old_kongfu()\n",
    "    learn.make_kongfu()\n",
    "    learn.make_master_kongfu()"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "ff4b1365-c152-40d0-b75e-a5247ebd3661",
   "metadata": {},
   "source": [
    "## 私有属性和方法\n",
    "### 定义私有属性和方法\n",
    "在Python中，可以为实例属性和方法设置私有权限，即设置了实例属性或实例方法不继承给子类。"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "61bfc49b-b2f2-4253-ac53-f3ad6a07b277",
   "metadata": {},
   "source": [
    "## 构造方法\n",
    "在类的方法中，有两种特殊的存在，分别在类的创建的时候调用\n",
    "它就是构造方法__init__()\n",
    "### 深入__init__()构造方法\n",
    "- __init__()方法属于魔法方法，但是他却是一个特殊的存在，在创建对象时，我们使用 【对象 = 类名()】 就可以实现，实际上，在每次创建对象后，系统就会马上调用__init__()方法，这个方法就被称为【构造方法】\n",
    "- 【每个类都有一个默认的构造方法】，如果我们自定义显式定义了__init__()方法，则创建完成后会调用这个定义的__init__()。如果在自定义类中没有定义__init__()方法，那么就会使用默认的__init__()方法，即创建对象后什么都不做，直接返回对象"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 2,
   "id": "a3547e1d-c780-4540-8ef7-494e2234645e",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "程序开始\n",
      "init 执行了，self =  <__main__.Person object at 0x000001F3D2CA0F80>\n",
      "程序结束 p1 =  <__main__.Person object at 0x000001F3D2CA0F80>\n"
     ]
    }
   ],
   "source": [
    "#观察__init__()\n",
    "#coding:UTF-8\n",
    "class Person:\n",
    "    def __init__(self):\n",
    "        \"\"\"__init__在创建对象时会自动执行\"\"\"\n",
    "        print('init 执行了，self = ', self)\n",
    "\n",
    "print('程序开始')\n",
    "p1 = Person()    #既然是构造含义，那么就意味着，这里不创建对象也能执行\n",
    "#当前如果不创建对象，就得直接写 类名()\n",
    "print('程序结束 p1 = ', p1)\n",
    "# 可以从执行结果中看出，self和当前对象地址一致，self代表的就是当前的对象"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 10,
   "id": "8860bee3-8389-4bdf-ad59-b8ab9c381ffe",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "姓名是：小蓝，学号是：11111\n"
     ]
    }
   ],
   "source": [
    "# 在__init__()方法中为Student对象添加两个对象属性\n",
    "#coding:UTF-8\n",
    "class Student:\n",
    "    def __init__(self, name, stuID):\n",
    "        self.name = name    #添加对象属性name\n",
    "        self.stuID = stuID\n",
    "\n",
    "if __name__ == '__main__':\n",
    "    #创建对象\n",
    "    xiaohong = Student('小红', 11267)\n",
    "    xiaohong.name = '小蓝'\n",
    "    xiaohong.stuID = 11111\n",
    "    print('姓名是：%s，学号是：%d' % (xiaohong.name, xiaohong.stuID))"
   ]
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Python 3 (ipykernel)",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.12.4"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 5
}
